package com.zzyl.intercept;


import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.ResourceMapper;
import com.zzyl.properties.JwtTokenProperties;
import com.zzyl.utils.JwtUtil;
import com.zzyl.utils.PathMatcherUtil;
import com.zzyl.utils.ThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class JwtTokenInterceptor implements HandlerInterceptor {
    @Autowired
    private JwtTokenProperties jwtTokenProperties;
    @Autowired
    private ResourceMapper resourceMapper;
    @Autowired
    StringRedisTemplate stringRedisTemplate;

    public boolean preHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler) throws Exception {
        log.info("用户端拦截器");
        String token = request.getHeader("Authorization");

        if (StrUtil.isEmpty(token)) {

            throw new BaseException(BasicEnum.SECURITY_ACCESSDENIED_FAIL);
        }

        //解析token
        Map<String, Object> claims = JwtUtil.parseJWT(jwtTokenProperties.getSecretKey(), token);
        if (ObjectUtil.isEmpty(claims)) {
            throw new BaseException(BasicEnum.SECURITY_ACCESSDENIED_FAIL);
        }

        Long id = Long.valueOf(claims.get("id").toString());

        if (ObjectUtil.isEmpty(id)) {
            throw new BaseException(BasicEnum.SECURITY_ACCESSDENIED_FAIL);
        }
        /*先查询redis,如果没有查询数据库,并且放入redis*/
        String redisKey = "zzyl:user:resource:path:" + id;

        //1. 通过redisKey获取数据
        String redisData = stringRedisTemplate.opsForValue().get(redisKey);
        List<String> requestPaths = null;

        //2. 判断redis中是否有数据
        if (StrUtil.isBlank(redisData)) {
            //没有数据，需要查询数据库
            //根据用户id查询对应的菜单（路径request_path）
            requestPaths = resourceMapper.selectListByUserId(id); //   POST/resource/enable
            //将查询的数据转json字符串，存入redis中
            stringRedisTemplate.opsForValue().set(redisKey, JSON.toJSONString(requestPaths));
            log.info("根据用户id查询数据库权限资源");
        } else {
            //3. 有数据，将redis中的数据转成 List<String>
            requestPaths = JSON.parseObject(redisData, List.class);
            log.info("根据用户id查询Redis权限资源");
        }

        //判断当前拦截器拦截的路径，是否在List集合中 getMethod表示请求方式  getRequestURI表示请求路径
        String url = request.getMethod() + request.getRequestURI();

        if (!PathMatcherUtil.match(requestPaths, url)) {
            //非法请求，权限不足
            throw new BaseException(BasicEnum.SECURITY_ACCESSDENIED_FAIL);
        }
        //把数据存储到线程中pending_tasks

        ThreadLocalUtil.set(id);

        return true;

  /* public void afterCompletion(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, Exception ex) throws Exception {
        ThreadLocalUtil.remove();
    }*/
    }
}
